﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Ribbon.Core.Event;
using Graphic = Ribbon.Core.Graphics.GraphicHelper;

namespace Ribbon.Core
{
    public interface IRibbonItem
    {
        RibbonGroup Parent { get; set; }

        Rect Rect { get; set; }

        Font Font { get; set; }

        SizeF Size { get; set; }

        PointF Location { get; set; }

        string Text { get; set; }

        Bitmap Image { get; set; }

        bool MaxImage { get; set; }

        bool IsMouseHover { get; set; }

        void OnPaint(System.Drawing.Graphics g);

        void OnMouseDown(MouseEventArgs e);

        void OnMouseMove(MouseEventArgs e);

        void OnMouseEnter(MouseEventArgs e);

        void OnMouseLeave(MouseEventArgs e);

        void Resize();
    }

    public class RibbonItem : IRibbonItem
    {
        public RibbonItem(string name)
        {
            this.Name = name;

            this.Text = name;

            this.foreColor = Color.Black;

            this.backColor = Color.FromArgb(238, 238, 242);

            this.borderColor = Color.FromArgb(209, 209, 209);

            this.selectBackColor = Color.FromArgb(209, 209, 209);
        }

        RibbonGroup parent;

        public RibbonGroup Parent
        {
            get
            {
                return parent;
            }
            set
            {
                parent = value;

                if (parent != null)
                {
                    Resize();
                }
            }
        }

        bool isMouseHover;

        public bool IsMouseHover
        {
            get
            {
                return isMouseHover;
            }
            set
            {
                isMouseHover = value;
            }
        }

        private bool maxImage;

        public bool MaxImage
        {
            get { return maxImage; }
            set { maxImage = value; }
        }

        /// <summary>
        /// 边界框
        /// </summary>
        private Rect rect;

        public Rect Rect
        {
            get { return rect; }
            set { rect = value; }
        }

        /// <summary>
        /// 坐标
        /// </summary>
        private PointF location;

        public PointF Location
        {
            get { return location; }
            set { location = value; }
        }

        /// <summary>
        /// 大小
        /// </summary>
        private SizeF size;

        public SizeF Size
        {
            get { return size; }
            set { size = value; }
        }

        /// <summary>
        /// 文本
        /// </summary>
        private string text;

        public string Text
        {
            get { return text; }
            set { text = value; }
        }

        private Font font;

        /// <summary>
        /// 字体
        /// </summary>
        public Font Font
        {
            get { return font; }
            set { font = value; }
        }

        /// <summary>
        ///
        /// </summary>
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private Bitmap image;

        public Bitmap Image
        {
            get { return image; }
            set { image = value; }
        }

        private int borderSize;

        public int BorderSize
        {
            get { return borderSize; }
            set { borderSize = value; }
        }

        private Color borderColor;

        public Color BorderColor
        {
            get { return borderColor; }
            set { borderColor = value; }
        }

        private Color backColor;

        public Color BackColor
        {
            get { return backColor; }
            set { backColor = value; }
        }

        private Color selectBackColor;

        public Color SelectBackColor
        {
            get { return selectBackColor; }
            set { selectBackColor = value; }
        }

        private Color foreColor;

        public Color ForeColor
        {
            get { return foreColor; }
            set { foreColor = value; }
        }

        private float radiu;

        public float Radiu
        {
            get { return radiu; }
            set { radiu = value; }
        }

        public event MouseClickDelegate MouseClick;

        public event MouseEnterDelegate MouseEnter;

        public event MouseMoveDelegate MouseMove;

        public event MouseLeaveDelegate MouseLeave;

        public void Resize()
        {
            if (this.Font == null)
                this.Font = parent.Font;

            if (this.rect == null)
            {
                this.Size = Graphic.Graphics.MeasureString(this.Text, this.Font);

                if (this.image != null)
                {
                    if (this.maxImage)
                    {
                        this.Rect = new Rect(parent.GroupRect.X + this.Location.X, parent.GroupRect.Y + this.Location.Y, this.Size.Width, this.Size.Height + 32);
                    }
                    else
                    {
                        this.Rect = new Rect(parent.GroupRect.X + this.Location.X, parent.GroupRect.Y + this.Location.Y, this.Size.Width + 21, this.Size.Height + 5);
                    }
                }
                else
                {
                    this.Rect = new Rect(parent.GroupRect.X + this.Location.X, parent.GroupRect.Y + this.Location.Y, this.Size.Width + 5, this.Size.Height + 5);
                }
            }

            if (parent.GroupRect.X + parent.GroupRect.Width < this.Rect.X + this.Rect.Width)
            {
                parent.GroupRect.Width += (this.Rect.X + this.Rect.Width + 5f) - (parent.GroupRect.X + parent.GroupRect.Width);
            }
        }

        public void OnPaint(System.Drawing.Graphics g)
        {
            if (this.isMouseHover)
            {
                using (SolidBrush bru_Background = new SolidBrush(selectBackColor))
                {
                    if (this.radiu > 1)
                    {
                        using (System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath())
                        {
                            path.AddLine(this.rect.X, this.rect.Y + this.rect.Height - this.radiu, this.rect.X, this.rect.Y + this.radiu);

                            path.AddArc(this.rect.X, this.rect.Y, this.radiu, this.radiu, 180, 90);

                            path.AddLine(this.rect.X + this.radiu, this.rect.Y, this.rect.X + this.rect.Width - this.radiu, this.rect.Y);

                            path.AddArc(this.rect.X + this.rect.Width - this.radiu, this.rect.Y, this.radiu, this.radiu, 270, 90);

                            path.AddLine(this.rect.X + this.rect.Width, this.rect.Y + this.radiu, this.rect.X + this.rect.Width, this.rect.Y + this.rect.Height - this.radiu);

                            path.AddArc(this.rect.X + this.rect.Width - this.radiu, this.rect.Y + this.rect.Height - this.radiu, this.radiu, this.radiu, 0, 90);

                            path.AddLine(this.rect.X + this.rect.Width - this.radiu, this.rect.Y + this.rect.Height, this.rect.X + this.radiu, this.rect.Y + this.rect.Height);

                            path.AddArc(this.rect.X, this.rect.Y + this.rect.Height - this.radiu, this.radiu, this.radiu, 90, 90);

                            g.FillPath(bru_Background, path);
                        }
                    }
                    else
                    {
                        g.FillRectangle(bru_Background, (int)this.rect.X, (int)this.rect.Y, (int)this.rect.Width, (int)this.rect.Height);
                    }
                }
            }

            float text_X = this.rect.X;

            float width = 0f;

            if (this.image != null)
            {
                if (this.maxImage)
                {

                }
                else
                {
                    g.DrawImage(this.image, new Rectangle((int)(this.rect.X + 5f), (int)(this.rect.Y + (this.rect.Height - this.image.Height) / 2), this.image.Width, this.image.Height));

                    text_X += this.image.Width;

                    width += this.image.Width + 5f;
                }
            }

            using (Brush bru_Text = new SolidBrush(foreColor))
            {
                g.DrawString(this.text, this.font, bru_Text, new RectangleF(text_X + 2.5f, this.rect.Y + 2.5f, this.rect.Width - width, this.rect.Height), new StringFormat(StringFormatFlags.FitBlackBox));
            }
        }

        public void OnMouseDown(MouseEventArgs e)
        {
            Console.WriteLine(this.name + "\t" + this.text + "\n");

            if (MouseClick != null)
            {
                MouseClick(this, e);
            }
        }


        public void OnMouseMove(MouseEventArgs e)
        {
            if (this.MouseMove != null)
            {
                this.MouseMove(this, e);
            }
        }

        public void OnMouseEnter(MouseEventArgs e)
        {
            if (this.MouseEnter != null)
            {
                this.MouseEnter(this, e);
            }
        }

        public void OnMouseLeave(MouseEventArgs e)
        {

        }
    }

    public class RibbonItemCollection : IList<IRibbonItem>
    {
        public RibbonItemCollection(RibbonGroup parent)
        {
            this.Parent = parent;

            this.Items = new List<IRibbonItem>();
        }

        private RibbonGroup Parent { get; set; }

        private List<IRibbonItem> Items;

        float TotalWidth = 10f;

        float Y1 = -1;

        float Y2 = -1;

        float Width1 = 0;

        float Width2 = 0;

        public int IndexOf(IRibbonItem item)
        {
            return Items.IndexOf(item);
        }

        public void Insert(int index, IRibbonItem item)
        {
            Items.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            Items.RemoveAt(index);

            this.Parent.Refresh();
        }

        public IRibbonItem this[int index]
        {
            get
            {
                return Items[index];
            }
            set
            {
                Items[index] = value;
            }
        }

        public void Add(IRibbonItem item)
        {
            item.Parent = this.Parent;

            Items.Add(item);

            this.Parent.Refresh();
        }

        public void AddRange(params IRibbonItem[] items)
        {
            foreach (IRibbonItem item in items)
            {
                item.Parent = this.Parent;

                Items.Add(item);
            }

            this.Parent.Refresh();
        }

        public void Clear()
        {
            Items.Clear();
        }

        public bool Contains(IRibbonItem item)
        {
            return Items.Contains(item);
        }

        public void CopyTo(IRibbonItem[] array, int arrayIndex)
        {
            CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return Items.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(IRibbonItem item)
        {
            return Items.Remove(item);
        }

        public IEnumerator<IRibbonItem> GetEnumerator()
        {
            return Items.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return Items.GetEnumerator();
        }
    }


    class Cell
    {
        public int Row { get; set; }

        public int Column { get; set; }

        public IRibbonItem Item { get; set; }
    }
}
